package com.yulinlin.authorization;


import com.yulinlin.common.pojo.AuthElement;
import com.yulinlin.common.util.RSAUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.codec.Base64;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author Zeny
 */
@SuppressWarnings("all")
@Slf4j
@EnableResourceServer
@Configuration
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private SpringApplicationUtil springApplicationUtil;

    @Value("${spring.application.name}:client")
    private String serverName;



    private List<String> authenticatedUrls(){
        Map<String,Object> map =  springApplicationUtil.getApplicationContext()
                .getBeansWithAnnotation(Controller.class);

        return map.values().stream().flatMap(row -> {

            return AuthElement.parseClass(serverName, row.getClass()).stream();
        }).map(AuthElement::getUrl).collect(Collectors.toList());

    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        List<String> urls =  authenticatedUrls();

        String[] authUrls =  urls.toArray(new String[urls.size()]);
        http
                // 由于使用的是JWT，我们这里不需要csrf
                .csrf().disable()


                // 基于token，所以不需要session
                .sessionManagement().disable()
                .headers()
                .cacheControl();

        if(!urls.isEmpty()){
            http.authorizeRequests()


                    .antMatchers(authUrls)
                    .authenticated();
        }

        http.authorizeRequests()

                .antMatchers("/**").permitAll();




    }

    /**
     * <h2>设置公钥</h2>
     *
     * @param resources
     **/
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenStore(jwtTokenStore());
    }

    private TokenStore jwtTokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    public SpringApplicationUtil SpringApplicationUtil(){
        return new SpringApplicationUtil();
    }


    @SneakyThrows
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        //resource 验证token（公钥）authorization产生token（私钥）
        JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();


        PublicKey publicKey =    RSAUtil.publicRsa().getPublicKey();


        String verifierKey = "-----BEGIN PUBLIC KEY-----\n" + new String(Base64.encode(publicKey.getEncoded())) + "\n-----END PUBLIC KEY-----";



        tokenConverter.setVerifierKey(verifierKey);


        return tokenConverter;
    }
}
